package string;

/**
 * 字符串常量池是JVM在堆内存中专门为了字符串提供的一段空间，用于缓存所有使用字面量形式创建的字符串对象，
 * 当再次使用相同字面量创建字符串时会直接重用常量池中的对象而不会再次创建新对象减少内存开销
 */
public class StringDemo {
    //运行代码快捷键：ctrl+shift+f10
    public static void main(String[] args) {
        String s1 = "123abc";
        System.out.println("s1:"+s1);

        String s2 = "123abc";//此处，虚拟机会在内存搜索之前有没有创建过123abc，如果有，那就指向同一个对象，不再创建
        System.out.println("s2:"+s2);
        System.out.println(s1==s2);//true  比较s1与s2的地址值,地址一样，说明都指向了同一个对象

        String s3 = new String("123abc");
        System.out.println(s3==s1);//false  当系统看到new后，会强制性创建新的对象

        System.out.println(s1.equals(s3));//true    equals比较的是字符串对象的内容

        s1 = s1 + "!";//原先的123abc没有变，重新创建了一个新的对象，s1指向新的对象，即地址发生改变
        System.out.println(s1);//123abc!    发生改变
        System.out.println(s2);//123abc     没有改变
        System.out.println(s1==s2);//false   s1的地址已经被更换了

        String s4 = "123"+"abc";//此代码在编译的时候，编译器直接进行编译，即在运行时s4就等于“123abc”
        System.out.println("s4:"+s4);//123abc
        System.out.println(s4==s2);//true

        String s = "123";
        String s5 = s + "abc";//此代码有变量，运行时会创建新的对象进行运算
        System.out.println("s5:"+s5);//123abc
        System.out.println(s5==s2);//false

        /**
         * 编译器有一个特性：
         * 当编译器在编译一段代码时发现一个计算表达式可以在编译期间确定结果时就会进行计算，并将结果编译到class文件中
         * 这样一来虚拟机运行该程序时就不必每次都进行计算了
         */
    }


}
